﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using UploadClient.Utilitys;

namespace UploadClient
{
    /// <summary>
    /// Serializeable custom list that manages the (connection) settings.
    /// </summary>
    public class ConnectionSettings : List<ServerSettings>, IXmlSerializable
    {

#if (DEBUG)
        private static readonly string path = Path.GetDirectoryName(Application.ExecutablePath);
#else
        //only in Releases
        private static string path = string.Format("{0}\\{1}", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 
                                                               Assembly.GetExecutingAssembly().GetName().Name.ToString());
#endif

        private readonly string filename = LocalizationManager.ResourceManager.GetString("DAT_0002");

        private ServerSettings selectedConnection;
        private ServerSettings favouriteConnection;

        /// <summary>
        /// The selected connection.
        /// </summary>
        public ServerSettings SelectedConnection { get { return selectedConnection; } set { selectedConnection = value; } }

        /// <summary>
        /// The favourite connection.
        /// </summary>
        public ServerSettings FavouriteConnection { get { return favouriteConnection; } set { favouriteConnection = value; } }

        /// <summary>
        /// Constructor with deserialization.
        /// </summary>
        /// <param name="deSerialize">If true it tryes to deserialize the connectionfile.</param>
        public ConnectionSettings(bool deSerialize = false)
        {
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            if (File.Exists(string.Format("{0}\\{1}", path, filename)))
            {
                //deserialize
                XmlSerializer deserializer = new XmlSerializer(typeof(ConnectionSettings));
                TextReader textReader = new StreamReader(string.Format("{0}\\{1}", path, filename));
                ConnectionSettings connectionSettings = (ConnectionSettings)deserializer.Deserialize(textReader);
                this.AddRange(connectionSettings);
                this.favouriteConnection = connectionSettings.FavouriteConnection;

                textReader.Close();
            }
        }

        /// <summary>
        /// Empty Constructor.
        /// </summary>
        private ConnectionSettings()
        {
        }

        /// <summary>
        /// Serialize the Object on dispose.
        /// </summary>
        ~ConnectionSettings()
        {
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            //serialize
            XmlSerializer serializer = new XmlSerializer(typeof(ConnectionSettings));
            TextWriter textWriter = new StreamWriter(string.Format("{0}\\{1}", path, filename));
            serializer.Serialize(textWriter, this);
            textWriter.Close();
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        /// <summary>
        /// Reads the XML into the object.
        /// </summary>
        /// <param name="reader"></param>
        public void ReadXml(XmlReader reader)
        {
            bool isFavourite = false;
            while (reader.Read())
            {
                try
                {
                    //ToDo: make it better ;-) (what if the order was mixed?) 
                    if (reader.NodeType.Equals(XmlNodeType.Element) && reader.Name.Equals("Settings"))
                    {
                        ServerSettings setting = new ServerSettings();
                        isFavourite = reader["Favourite"].Equals("True") ? true : false;

                        reader.ReadStartElement();
                        setting.Host = reader.ReadElementContentAsString();
                        setting.Username = reader.ReadElementContentAsString();
                        setting.Password = Encryption.DecryptString(reader.ReadElementContentAsString(), PasswordHash.GenerateHash());
                        setting.Passive = reader.ReadElementContentAsString().Equals("True") ? true : false;
                        setting.Port = reader.ReadElementContentAsInt();

                        Add(setting);
                        if (isFavourite) favouriteConnection = setting;
                    }
                }
                catch (Exception ex)
                {
                    new Exception(string.Format(LocalizationManager.ResourceManager.GetString("ERR_0003"), path, filename),ex);
                }
            }
        }

        /// <summary>
        /// Writes to the XML.
        /// </summary>
        /// <param name="writer">The XmlWriter.</param>
        public void WriteXml(XmlWriter writer)
        {
            bool isFavourite = false;
            foreach (ServerSettings setting in this)
            {
                isFavourite = favouriteConnection != null && favouriteConnection.Equals(setting) ? true : false;

                writer.WriteStartElement("Settings");
                writer.WriteAttributeString("Favourite", isFavourite.ToString());
                writer.WriteElementString("Host", setting.Host.ToString());
                writer.WriteElementString("Username", setting.Username.ToString());
                writer.WriteElementString("Password", Encryption.EncryptString(setting.Password, PasswordHash.GenerateHash()));
                writer.WriteElementString("Passive", setting.Passive.ToString());
                writer.WriteElementString("Port", setting.Port.ToString());
                writer.WriteEndElement();
            }
        }
    }
}
